package com.hytc.mymall.http;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.ImageView;

import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.IOException;
import java.net.URLConnection;
import java.util.Map;
import java.util.Set;


/**
 * Created by Administrator on 2016/12/1.
 */

public class OkHttpClientManager
{
    private static OkHttpClientManager mInstance;
    private Handler mDelivery;
    private OkHttpClient mOkHttpClient;

    private OkHttpClientManager() {
        this.mOkHttpClient = new OkHttpClient();
        this.mDelivery = new Handler(Looper.getMainLooper());
    }

    private void _displayImage(final ImageView imageView, final String s, final int n) {
    }

    private void _downloadAsyn(final String s, final String s2, final StringCallback stringCallback) {
        this.mOkHttpClient.newCall(new Request.Builder().url(s).build()).enqueue(new Callback() {
            @Override
            public void onFailure(final Request request, final IOException ex) {
                OkHttpClientManager.this.sendFailedStringCallback(request, ex, stringCallback);
            }

            @Override
            public void onResponse(final Response p0) {
                throw new IllegalStateException("An error occurred while decompiling this method.");
            }
        });
    }

    private String _getAsString(final String s) throws IOException {
        return this._getAsyn(s).body().string();
    }

    private Response _getAsyn(final String s) throws IOException {
        return this.mOkHttpClient.newCall(new Request.Builder().url(s).build()).execute();
    }

    private void _getAsyn(final String s, final StringCallback stringCallback) {
        Log.e("TAG","s："+s);
        Log.e("TAG","String:"+stringCallback.toString());
        this.deliveryResult(stringCallback, new Request.Builder().url(s).build());
    }

    private Response _post(final String s, final File file, final String s2) throws IOException {
        return this.mOkHttpClient.newCall(this.buildMultipartFormRequest(s, new File[] { file }, new String[] { s2 }, null)).execute();
    }

    private Response _post(final String s, final File file, final String s2, final Param... array) throws IOException {
        return this.mOkHttpClient.newCall(this.buildMultipartFormRequest(s, new File[] { file }, new String[] { s2 }, array)).execute();
    }

    private Response _post(final String s, final Param... array) throws IOException {
        return this.mOkHttpClient.newCall(this.buildPostRequest(s, array)).execute();
    }

    private Response _post(final String s, final File[] array, final String[] array2, final Param... array3) throws IOException {
        return this.mOkHttpClient.newCall(this.buildMultipartFormRequest(s, array, array2, array3)).execute();
    }

    private String _postAsString(final String s, final Param... array) throws IOException {
        return this._post(s, array).body().string();
    }

    private void _postAsyn(final String s, final StringCallback stringCallback, final File file, final String s2) throws IOException {
        this.deliveryResult(stringCallback, this.buildMultipartFormRequest(s, new File[] { file }, new String[] { s2 }, null));
    }

    private void _postAsyn(final String s, final StringCallback stringCallback, final File file, final String s2, final Map<String, String> map) throws IOException {
        this.deliveryResult(stringCallback, this.buildMultipartFormRequest(s, new File[] { file }, new String[] { s2 }, this.map2Params(map)));
    }

    private void _postAsyn(final String s, final StringCallback stringCallback, final File file, final String s2, final Param... array) throws IOException {
        this.deliveryResult(stringCallback, this.buildMultipartFormRequest(s, new File[] { file }, new String[] { s2 }, array));
    }

    private void _postAsyn(final String s, final StringCallback stringCallback, final Map<String, String> map) {
        this.deliveryResult(stringCallback, this.buildPostRequest(s, this.map2Params(map)));
    }

    private void _postAsyn(final String s, final StringCallback stringCallback, final Param... array) {
        this.deliveryResult(stringCallback, this.buildPostRequest(s, array));
    }

    private void _postAsyn(final String s, final StringCallback stringCallback, final File[] array, final String[] array2, final Param... array3) throws IOException {
        this.deliveryResult(stringCallback, this.buildMultipartFormRequest(s, array, array2, array3));
    }

    private Request buildMultipartFormRequest(final String s, final File[] array, final String[] array2, final Param[] array3) {
        final Param[] validateParam = this.validateParam(array3);
        final MultipartBuilder type = new MultipartBuilder().type(MultipartBuilder.FORM);
        for (final Param param : validateParam) {
            type.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + param.key + "\""), RequestBody.create(null, param.value));
        }
        if (array != null) {
            for (int j = 0; j < array.length; ++j) {
                final File file = array[j];
                final String name = file.getName();
                type.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + array2[j] + "\"; filename=\"" + name + "\""), RequestBody.create(MediaType.parse(this.guessMimeType(name)), file));
            }
        }
        return new Request.Builder().url(s).post(type.build()).build();
    }

    private Request buildPostRequest(final String s, Param[] array) {
        int i = 0;
        if (array == null) {
            array = new Param[0];
        }
        final FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();
        while (i < array.length) {
            final Param param = array[i];
            formEncodingBuilder.add(param.key, param.value);
            ++i;
        }
        return new Request.Builder().url(s).post(formEncodingBuilder.build()).build();
    }

    private void deliveryResult(final StringCallback stringCallback, final Request request) {
        stringCallback.onBeforeRequest(request);
        this.mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(final Request request, final IOException ex) {
                OkHttpClientManager.this.sendFailedStringCallback(request, ex, stringCallback);
            }

            @Override
            public void onResponse(final Response response) {
                OkHttpClientManager.this.sendResponseStringCallback(stringCallback);
                try {
                    OkHttpClientManager.this.sendSuccessStringCallback(response.body().string(), stringCallback);
                }
                catch (IOException ex) {
                    OkHttpClientManager.this.sendFailedStringCallback(response.request(), ex, stringCallback);
                }
            }
        });
    }

    public static void displayImage(final ImageView imageView, final String s) {
        getInstance()._displayImage(imageView, s, -1);
    }

    public static void displayImage(final ImageView imageView, final String s, final int n) throws IOException {
        getInstance()._displayImage(imageView, s, n);
    }

    public static void downloadAsyn(final String s, final String s2, final StringCallback stringCallback) {
//        getInstance()._downloadAsyn(s, s2, stringCallback);
    }

    public static String getAsString(final String s) throws IOException {
        return getInstance()._getAsString(s);
    }

    public static Response getAsyn(final String s) throws IOException {
        return getInstance()._getAsyn(s);
    }

    public static void getAsyn(final String s, final StringCallback stringCallback) {
        getInstance()._getAsyn(s, stringCallback);
    }

    private String getFileName(final String s) {
        final int lastIndex = s.lastIndexOf("/");
        if (lastIndex < 0) {
            return s;
        }
        return s.substring(lastIndex + 1, s.length());
    }

    public static OkHttpClientManager getInstance() {

            if (OkHttpClientManager.mInstance != null) {
                return OkHttpClientManager.mInstance;
            }
            synchronized (OkHttpClientManager.class) {
                if (OkHttpClientManager.mInstance == null) {
                    OkHttpClientManager.mInstance = new OkHttpClientManager();
                }
                return OkHttpClientManager.mInstance;
            }
    }

    private String guessMimeType(final String s) {
        String contentType = URLConnection.getFileNameMap().getContentTypeFor(s);
        if (contentType == null) {
            contentType = "application/octet-stream";
        }
        return contentType;
    }

    private Param[] map2Params(final Map<String, String> map) {
        Param[] array;
        if (map == null) {
            array = new Param[0];
        }
        else {
            array = new Param[map.size()];
            final Set<Map.Entry<String, String>> entrySet = map.entrySet();
            int n = 0;
            for (final Map.Entry<String, String> entry : entrySet) {
                final int n2 = n + 1;
                array[n] = new Param(entry.getKey(), entry.getValue());
                n = n2;
            }
        }
        return array;
    }

    public static Response post(final String s, final File file, final String s2) throws IOException {
        return getInstance()._post(s, file, s2);
    }

    public static Response post(final String s, final File file, final String s2, final Param... array) throws IOException {
        return getInstance()._post(s, file, s2, array);
    }

    public static Response post(final String s, final Param... array) throws IOException {
        return getInstance()._post(s, array);
    }

    public static Response post(final String s, final File[] array, final String[] array2, final Param... array3) throws IOException {
        return getInstance()._post(s, array, array2, array3);
    }

    public static String postAsString(final String s, final Param... array) throws IOException {
        return getInstance()._postAsString(s, array);
    }

    public static void postAsyn(final String s, final StringCallback stringCallback, final File file, final String s2) throws IOException {
        getInstance()._postAsyn(s, stringCallback, file, s2);
    }

    public static void postAsyn(final String s, final StringCallback stringCallback, final File file, final String s2, final Param... array) throws IOException {
        getInstance()._postAsyn(s, stringCallback, file, s2, array);
    }

    public static void postAsyn(final String s, final StringCallback stringCallback, final Map<String, String> map) {
        getInstance()._postAsyn(s, stringCallback, map);
    }

    public static void postAsyn(final String s, final StringCallback stringCallback, final Param... array) {
        getInstance()._postAsyn(s, stringCallback, array);
    }

    public static void postAsyn(final String s, final StringCallback stringCallback, final File[] array, final String[] array2, final Param... array3) throws IOException {
        getInstance()._postAsyn(s, stringCallback, array, array2, array3);
    }

    private void sendFailedStringCallback(final Request request, final IOException ex, final StringCallback stringCallback) {
        this.mDelivery.post((Runnable)new Runnable() {
            @Override
            public void run() {
                if (stringCallback != null) {
                    stringCallback.onFailure(request, ex);
                }
            }
        });
    }

    private void sendResponseStringCallback(final StringCallback stringCallback) {
        this.mDelivery.post((Runnable)new Runnable() {
            @Override
            public void run() {
                if (stringCallback != null) {
                    stringCallback.onSuccess();
                }
            }
        });
    }

    private void sendSuccessStringCallback(final String s, final StringCallback stringCallback) {
        this.mDelivery.post((Runnable)new Runnable() {
            @Override
            public void run() {
                if (stringCallback != null) {
                    stringCallback.onResponse(s);
                }
            }
        });
    }

    private void setErrorResId(final ImageView imageView, final int n) {
        this.mDelivery.post((Runnable)new Runnable() {
            @Override
            public void run() {
                imageView.setImageResource(n);
            }
        });
    }

    private Param[] validateParam(Param[] array) {
        if (array == null) {
            array = new Param[0];
        }
        return array;
    }

    public static class Param
    {
        String key;
        String value;

        public Param() {
        }

        public Param(final String key, final String value) {
            this.key = key;
            this.value = value;
        }
    }
}
